package com.xdw.distributedvideoplayer.slice;

import com.xdw.distributedvideoplayer.ResourceTable;
import com.xdw.distributedvideoplayer.component.Toast;
import com.xdw.distributedvideoplayer.provider.CommonProvider;
import com.xdw.distributedvideoplayer.provider.ViewProvider;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.*;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.SurfaceOps;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.service.Window;
import ohos.agp.window.service.WindowManager;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.app.dispatcher.task.Revocable;
import ohos.distributedschedule.interwork.DeviceInfo;
import ohos.distributedschedule.interwork.DeviceManager;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.common.Source;
import ohos.media.player.Player;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import static ohos.media.player.Player.VIDEO_SCALE_TYPE_CROP;

public class MainAbilitySlice extends AbilitySlice implements Player.IPlayerCallback, Component.ClickedListener {
    private static final int DELAY_TIME_CONTROL = 5000;
    private static final String TAG = "MainAbilitySlice";   //定义日志tag
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, TAG);  //定义日志label
    private SurfaceProvider mSurfaceProvider;   //定义一个SurfaceProvider控件，用来呈现视频
    private Player mPlayer; //定义一个Player，用来控制视频流
    private SurfaceOps mSurfaceOps;
    private TaskDispatcher uiTaskDispatcher;    //定义UI线程任务分发器，子线程中更新UI主线程需要使用它
    private Revocable revocableBootomControl;   //定义底部导航栏3秒后定时消失的异步任务
    private AnimatorProperty loadingAnimator;   //加载等待框的属性动画，用来实现转圈效果
    //start---定义控制栏相关UI组件---start
    private DependentLayout dlPlayer;  //视频窗口包括控制栏的容器
    private DirectionalLayout dlBootomControl; //底部的控制栏
    private Slider sliderBarVedio;  //视频播放进度条
    private Image imgPlay, imgFullScreen;
    private DirectionalLayout dlBeisu;
    private Text textBeisu, textBeisu15, textBeisu1, textBeisu05;
    private RoundProgressBar rpbLoading;
    //end---定义控制栏相关UI组件---end
    private boolean screenFullFlag = false;  //标记当前是否是全屏，默认是非全屏的
    private ComponentContainer.LayoutConfig oldLayoutConfig; //视频窗口全屏之前的布局配置，用来从全屏还原到半屏
    private Text textTotalTime; //定义显示视频总时长的组件
    private Text textCurrentTime;   //定义视频实时播放时间的组件

    //定义视频播放时间计算相关的成员变量，时间显示格式为00:00，冒号前面是分钟，后面是秒
    //小于10分钟或者10秒的前面补充0，大于10分钟或者十秒的正常显示位数，3位数的也正常显示3位数
    private int totalTime;      //定义视频播放总时长，单位为秒，api获取的时间单位默认为毫秒
    private int currentTime;    //视频当前播放时间，单位为秒，api获取的时间单位默认为毫秒
    private Timer updateCurrenttimeTimer = new Timer();  //用来实时更新播放器

    private boolean isShowDlBeisuFlag = false;  //定义一个用来标示倍速控制的那行布局是否显示的flag，ture代表显示，默认不显示

    //定义存放设备列表数据的list
    private List<DeviceInfo> devices = new ArrayList<>(0);
    //定义deviceListContainer成员变量
    private ListContainer deviceListContainer;
    //定义imageTv成员变量，该图片按钮用于触发分布式流转业务
    private Image imageTv;
    //定义toast显示时长
    private static final int TOAST_DURATION = 3000;
    //定义自定义弹框，加载搜索到的可以进行分布式协同的设备列表
    private  CommonDialog devicesDialog;
    // 关键回调，呈现视频的空间创建好之后开始初始化视频流Player的相关操作
    private SurfaceOps.Callback mSurfaceCallback = new SurfaceOps.Callback() {
        @Override
        public void surfaceCreated(SurfaceOps surfaceOps) {
            //视频播放前加载框转圈
            if (!loadingAnimator.isRunning()) {
                loadingAnimator.start();
            }
            //设置本地视频源，必须首先设置这个，否则无法播放视频
            //mPlayer.setSource(getContext().getResourceManager().getRawFileEntry("resources/rawfile/a.mp4").openRawFileDescriptor());
            //设置网络视频
            mPlayer.setSource(new Source("https://mm-xdw.obs.cn-north-4.myhuaweicloud.com/tuhua.mp4"));
            //设置视频播放的窗口，player绑定suface，核心操作，将视频流与UI容器组件关联起来
            mPlayer.setVideoSurface(mSurfaceProvider.getSurfaceOps().get().getSurface());

            //设置视频循环播放，不是必须的
            mPlayer.enableSingleLooping(true);
            //设置视频准备播放，注意这里不是直接调用play方法，而是先调用prepare，后面在prepared回调里面再调用play，意思就是准备好之后再播放
            mPlayer.prepare();
        }

        @Override
        public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {

        }

        @Override
        public void surfaceDestroyed(SurfaceOps surfaceOps) {
            mPlayer.stop();
        }
    };

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        // 开发者动态申请需要使用的敏感权限
        requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC"}, 0);
        //初始化视频启动播放时间，如果是通过分布式启动的获取外部传递过来的初始化起始时间
        currentTime = intent.getIntParam("INTENT_STARTTIME_PARAM", 0);
        Toast.toast(this,"currentTime="+currentTime,TOAST_DURATION);
        uiTaskDispatcher = getUITaskDispatcher();
        initView();
        initPlayer();
        initEvent();
        //初始化加载框的动画
        loadingAnimator = rpbLoading.createAnimatorProperty();
        loadingAnimator.rotate(360).setDuration(2000).setDelay(500).setLoopedCount(-1);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    private void initView() {
        mSurfaceProvider = (SurfaceProvider) findComponentById(ResourceTable.Id_sp);
//        mSurfaceOps = mSurfaceProvider.getSurfaceOps().get();
        //为了让suface窗口能够播放视频，可以将ztop设置为true，但是这样视频窗口后面就不能在上面自定义控制栏了
        //因此将ztop设置ztop为false，为false的时候必须将窗口背景设置为透明视频才能显示，否则黑屏
        mSurfaceProvider.pinToZTop(false);
        //设置页面背景透明
        WindowManager windowManager = WindowManager.getInstance();
        Window window = windowManager.getTopWindow().get();
        window.setTransparent(true);

        dlPlayer = (DependentLayout) findComponentById(ResourceTable.Id_dl_player);
        oldLayoutConfig = dlPlayer.getLayoutConfig();   //保存全屏之前的布局，以便后面还原成非全屏状态
        dlBootomControl = (DirectionalLayout) findComponentById(ResourceTable.Id_dl_bottom_control);
        imgPlay = (Image) findComponentById(ResourceTable.Id_img_play);
        dlBeisu = (DirectionalLayout) findComponentById(ResourceTable.Id_dl_beisu);
        textBeisu = (Text) findComponentById(ResourceTable.Id_text_beisu);
        textBeisu15 = (Text) findComponentById(ResourceTable.Id_text_beisu15);
        textBeisu1 = (Text) findComponentById(ResourceTable.Id_text_beisu1);
        textBeisu05 = (Text) findComponentById(ResourceTable.Id_text_beisu05);
        imgFullScreen = (Image) findComponentById(ResourceTable.Id_img_full_screen);
        sliderBarVedio = (Slider) findComponentById(ResourceTable.Id_slider_vedio);
        rpbLoading = (RoundProgressBar) findComponentById(ResourceTable.Id_rpb_loading);
        textTotalTime = (Text) findComponentById(ResourceTable.Id_text_total_time);
        textCurrentTime = (Text) findComponentById(ResourceTable.Id_text_current_time);

        //初始化imageTv
        imageTv = (Image)findComponentById(ResourceTable.Id_tv);
        //初始化自定义对话框
        intDevicesDialog();

    }

    private void initEvent() {
        dlPlayer.setClickedListener(this);
        dlBootomControl.setClickedListener(this);
        imgPlay.setClickedListener(this);
        dlBeisu.setClickedListener(this);
        textBeisu.setClickedListener(this);
        textBeisu15.setClickedListener(this);
        textBeisu1.setClickedListener(this);
        textBeisu05.setClickedListener(this);
        imgFullScreen.setClickedListener(this);
        sliderBarVedio.setClickedListener(this);
        sliderBarVedio.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int i, boolean b) {

            }

            //拖动开始的时候，这里后面需要在这里关闭之前的定时器来进行优化，不然拖动和之前的定时更新进度条有冲突不流畅
            @Override
            public void onTouchStart(Slider slider) {
            }

            //拖动结束的时候
            @Override
            public void onTouchEnd(Slider slider) {
                int progress = sliderBarVedio.getProgress();    //获取进度条进度
                mPlayer.rewindTo(progress * 1000 * 1000);   //重定位播放进度，注意这里进度是微秒单位
            }
        });

        //添加图片按钮点击事件
        imageTv.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                //初始化设备列表数据
                initDevices();
                //显示加载数据列表
                showDeviceList();
            }
        });

        deviceListContainer.setItemClickedListener(new ListContainer.ItemClickedListener() {
            @Override
            public void onItemClicked(ListContainer listContainer, Component component, int num, long l) {
                Toast.toast(MainAbilitySlice.this, "click successful！", TOAST_DURATION);
                //实现跨设备启动FA
                Intent intent = new Intent();
                Operation operation = new Intent.OperationBuilder()
                        .withDeviceId(devices.get(num).getDeviceId())
                        .withBundleName("com.xdw.distributedvideoplayer")
                        .withAbilityName("com.xdw.distributedvideoplayer.MainAbility")
                        .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
                        .build();
                intent.setOperation(operation);
                intent.setParam("INTENT_STARTTIME_PARAM", currentTime);

                startAbility(intent);
            }
        });
    }

    //定义初始化player的操作
    private void initPlayer() {
        mPlayer = new Player(this); //创建player对象
        mPlayer.setVideoScaleType(VIDEO_SCALE_TYPE_CROP);   //设置视频缩放类型
        mSurfaceProvider.getSurfaceOps().get().addCallback(mSurfaceCallback);   //player与surface回调绑定
        mPlayer.setPlayerCallback(this);
    }

    //player的回调
    @Override
    public void onPrepared() {
        HiLog.error(LABEL, "onPrepared");
        //视频准备好之后开始播放，从记录的播放时间点开始进行播放
        if (currentTime > 0) {
            mPlayer.play();
            mPlayer.rewindTo(currentTime * 1000*1000);
        } else {
            mPlayer.play();
        }
        totalTime = mPlayer.getDuration() / 1000; //总时长默认单位为毫秒，转化为秒
        //视频prepared之后设置进度条的最大值和最小值
        sliderBarVedio.setMaxValue(totalTime);
        sliderBarVedio.setMinValue(0);

        //定义一个定时任务，用来实时更新当前播放时间和进度条进度
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                currentTime = mPlayer.getCurrentTime() / 1000; //总时长默认单位为毫秒，转化为秒
                uiTaskDispatcher.asyncDispatch(new Runnable() {
                    @Override
                    public void run() {
                        textCurrentTime.setText(timeToFormatString(currentTime));   //更新当前时间显示
                        sliderBarVedio.setProgressValue(currentTime);   //更新进度条进度
                    }
                });
            }
        };
        //启动定时任务，每500毫秒执行一次
        updateCurrenttimeTimer.schedule(timerTask, 0, 500);

        //视频准备好之后显示控制栏,并且设置总时长
        uiTaskDispatcher.asyncDispatch(new Runnable() {
            @Override
            public void run() {
                textTotalTime.setText(timeToFormatString(totalTime));
                imgPlay.setPixelMap(ResourceTable.Media_pause);
                dlBootomControl.setVisibility(Component.VISIBLE);
            }
        });
        //3秒之后自动隐藏控制栏
        revocableBootomControl = uiTaskDispatcher.delayDispatch(new Runnable() {
            @Override
            public void run() {
                dlBootomControl.setVisibility(Component.INVISIBLE);
            }
        }, DELAY_TIME_CONTROL);
    }

    @Override
    public void onMessage(int i, int i1) {
        HiLog.error(LABEL, "onMessage i=" + i);
        //在视频缓冲加载开始和加载完成都会触发此回调，通过第一个参数i进行判断，
        // Player.PLAYER_INFO_BUFFERING_START代表开始缓冲，Player.PLAYER_INFO_BUFFERING_END代表结束缓冲
        switch (i) {
            //开始缓冲，显示加载等待框
            case Player.PLAYER_INFO_BUFFERING_START:
                uiTaskDispatcher.asyncDispatch(new Runnable() {
                    @Override
                    public void run() {
                        rpbLoading.setVisibility(Component.VISIBLE);
                    }
                });
                break;
            //结束缓冲，隐藏加载等待框
            case Player.PLAYER_INFO_VIDEO_RENDERING_START:
            case Player.PLAYER_INFO_BUFFERING_END:
                uiTaskDispatcher.asyncDispatch(new Runnable() {
                    @Override
                    public void run() {
                        rpbLoading.setVisibility(Component.INVISIBLE);
                    }
                });
                break;
        }
    }

    @Override
    public void onError(int i, int i1) {
        HiLog.error(LABEL, "onError");
    }

    @Override
    public void onResolutionChanged(int i, int i1) {
        HiLog.error(LABEL, "onResolutionChanged");
    }

    @Override
    public void onPlayBackComplete() {
        HiLog.error(LABEL, "onPlayBackComplete");
    }

    @Override
    public void onRewindToComplete() {
        HiLog.error(LABEL, "onRewindToComplete");
    }

    @Override
    public void onBufferingChange(int i) {
        HiLog.error(LABEL, "onBufferingChange");
    }

    @Override
    public void onNewTimedMetaData(Player.MediaTimedMetaData mediaTimedMetaData) {

    }

    @Override
    public void onMediaTimeIncontinuity(Player.MediaTimeInfo mediaTimeInfo) {

    }

    @Override
    public void onClick(Component component) {

        switch (component.getId()) {
            //点击播放器窗口的时候，显示控制栏，3秒之后隐藏控制栏
            case ResourceTable.Id_dl_player:
                //首先判断之前是否存在异步任务，存在则先取消之前的定时任务
                if (revocableBootomControl != null) {
                    revocableBootomControl.revoke();
                }
                //显示控制栏
                dlBootomControl.setVisibility(Component.VISIBLE);
                //3秒后隐藏控制栏
                revocableBootomControl = uiTaskDispatcher.delayDispatch(new Runnable() {
                    @Override
                    public void run() {
                        dlBootomControl.setVisibility(Component.INVISIBLE);
                    }
                }, DELAY_TIME_CONTROL);
                break;
            case ResourceTable.Id_img_play:
                //点击之后，正在播放则暂停，暂停则播放
                if (mPlayer.isNowPlaying()) {
                    mPlayer.pause();
                    imgPlay.setPixelMap(ResourceTable.Media_play);
                } else {
                    mPlayer.play();
                    imgPlay.setPixelMap(ResourceTable.Media_pause);
                }
                break;
            //全屏和非全屏切换
            case ResourceTable.Id_img_full_screen:
                if (!screenFullFlag) {
                    DependentLayout.LayoutConfig lp = new DependentLayout.LayoutConfig(DependentLayout.LayoutConfig.MATCH_PARENT,
                            DependentLayout.LayoutConfig.MATCH_PARENT);
                    dlPlayer.setLayoutConfig(lp);
                    screenFullFlag = true;
                } else {
                    dlPlayer.setLayoutConfig(oldLayoutConfig);
                    screenFullFlag = false;
                }
                ;
                break;
            //点击播放进度条跳转播放进度
            case ResourceTable.Id_slider_vedio:
                int progress = sliderBarVedio.getProgress();    //获取进度条进度
                mPlayer.rewindTo(progress * 1000 * 1000);   //重定位播放进度，注意这里进度是微秒单位
                break;
            //点击倍速，弹出或者隐藏倍速选择栏
            case ResourceTable.Id_text_beisu:
                if (isShowDlBeisuFlag) {
                    dlBeisu.setVisibility(Component.INVISIBLE);
                    isShowDlBeisuFlag = false;
                } else {
                    dlBeisu.setVisibility(Component.VISIBLE);
                    isShowDlBeisuFlag = true;
                }
                break;
            //1倍播放速度
            case ResourceTable.Id_text_beisu1:
                mPlayer.setPlaybackSpeed(1);
                setAllBeisuColorDefault();
                textBeisu1.setTextColor(Color.GREEN);
                break;
            //1.5倍播放速度
            case ResourceTable.Id_text_beisu15:
                mPlayer.setPlaybackSpeed(1.5f);
                setAllBeisuColorDefault();
                textBeisu15.setTextColor(Color.GREEN);
                break;
            //0.5倍播放速度
            case ResourceTable.Id_text_beisu05:
                mPlayer.setPlaybackSpeed(0.5f);
                setAllBeisuColorDefault();
                textBeisu05.setTextColor(Color.GREEN);
                break;
        }
    }

    /**
     * 将时间戳格式为00:00格式的显示
     *
     * @param time 时间，单位为秒
     * @return
     */
    private String timeToFormatString(int time) {
        int minites = time / 60;
        int seconds = time % 60;
        String minStr = minites > 10 ? String.valueOf(minites) : "0" + String.valueOf(minites);
        String secStr = seconds > 10 ? String.valueOf(seconds) : "0" + String.valueOf(seconds);
        return new StringBuilder(minStr).append(":").append(secStr).toString();
    }

    /**
     * 定义一个将所有倍速按钮设置成默认白色的方法，在切换倍速的时候调用
     */
    private void setAllBeisuColorDefault() {
        textBeisu1.setTextColor(Color.WHITE);
        textBeisu15.setTextColor(Color.WHITE);
        textBeisu05.setTextColor(Color.WHITE);
    }

    /**
     * 查找可以进行分布式协同的设备，并且存储到devices中
     */
    private void initDevices() {
        if (devices.size() > 0) {
            devices.clear();
        }
        List<DeviceInfo> deviceInfos = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
        devices.addAll(deviceInfos);
    }

    /**
     * 对设备列表ListContainer组件进行渲染
     */
    private void showDeviceList() {
        CommonProvider commonProvider = new CommonProvider<DeviceInfo>(devices, getContext(),
                ResourceTable.Layout_device_list_item) {
            @Override
            protected void convert(ViewProvider viewProvider, DeviceInfo item, int position) {
                viewProvider.setText(ResourceTable.Id_device_text, item.getDeviceName());
            }
        };
        deviceListContainer.setItemProvider(commonProvider);
        commonProvider.notifyDataChanged();
        devicesDialog.show();
    }


    /**
     * 初始化设备列表弹框
     */
    private void intDevicesDialog(){
        devicesDialog = new CommonDialog(this);
        Component dialogComponent = LayoutScatter.getInstance(getContext())
                .parse(ResourceTable.Layout_remote_devices_dialog, null, true);
        devicesDialog.setContentCustomComponent(dialogComponent);
        deviceListContainer = (ListContainer) dialogComponent.findComponentById(ResourceTable.Id_device_list_container);
    }
}
